home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-13 | 24.4 KB | 820 lines | [TEXT/MPS ] |
- // Tumbler_drag.c
- //
- // Dragging routines. The code in this file implements the geometry
- // dragging features of this program. The last function in this file,
- // DoDragObjects is called when a mouseDown is detected in the hilite region
- // of the current object.
- //
- // Here's some background from Nick for debugging this mess. First off the drag manager
- // is not a simple animal.
- //
- // High-level or source-level debuggers won't work with Drag Manager callback routines.
- // That's because of the way the Drag Manager performs process switching. The only
- // high-level debugger that does work with the Drag Manager is VoodooMonkey, an "experimental
- // prototype" debugger you can find on the November Developer CD. Note that VoodooMonkey
- // is unsupported by Apple. The other more-supportable option is to use MacsBug (or your
- // favorite low-level debugger) for real-time debugging. But since this 3d stuff will only
- // work on power macintosh cpu's (unless you have the souce code, which developers don't :0>)
- // MacsBug won't help you much. And I was using a version of CodeWarrior that didn't seem to
- // want to put any symbols in, which means Macsbug is not really an option (debugging what
- // MB thinks is the 68k equivalent of the actual PPC instructions, with no symbols, ain't
- // my idea of fun. And don't think DebugStr will help you any - if you are running with
- // the MetroWerks (MW) high level debugger, your mAchine will crash big time. MW debugger
- // wants to display the debugstr in a nice little dialog, which means it has to do a context
- // switch. Why is this bad... read on McDuff:
- //
- // The Drag Manager is actually making full context switches for each process that has
- // tracking/receive handlers as an object is dragged over a valid drag region. While this
- // may sound a bit drastic or scary, it isn't really that bad because a drag is a modal operation,
- // and as long as the user is dragging an object, the System (namely the Drag Manager) is in
- // control to call tracking and receive handlers as appropriate. So when your receive handler
- // is called and all events pending for your process have been handled, your application is
- // eliglble for a context switch the next time WaitNextEvent is called. And when WNE is called
- // and a context switch occurs, the Drag Manager has lost track over what process is currently
- // the context. This is also why you cannot use source-level debuggers to debug drag handlers,
- // because context switches are controlled by those debuggers, and once you're in a Drag you
- // cannot change the Process Manager state.
- //
- // In case you're interested, one technique that works well for receive handlers is to send an
- // Apple event to yourself with the relevant information about the drag, and process it at
- // WaitNextEvent time. Sending an Apple event to yourself can be done even if you're not the
- // frontmost application, and it allows you to process the Drag at WaitNextEvent time, meaning
- // you can call your Alert routine and change process states without any problems. Another
- // benefit to this approach is that you'll be able to use source level debuggers to work on
- // your receive handlers.
- //
- // The only thing to beware of if you do this (and this is what do here) is to get the PSN
- // directly - AppleEvents.h gives a constant (kCurrentProcess) that you can stick in the low
- // longword of the PSN that will cause the event to essentially be dispatched as a function
- // call, and that is not what we want here. By getting the process serial number (PSN) of
- // our own process and using that in the AppleEvent we ensure that the event is dispatched
- // to our process so we can deal with it in the main event loop, rather than being mapped into
- // and unwanted funtion call (which since we would still be in the drag managers context would
- // prevent us from being able to debug using anything reasonable). Check out Tumbler_AEVT for
- // more details on this.
- //
- // Nitin Gantatra whined so much that I'd stolen the comments above, that I feel compelled to
- // add:
- //
- // Author of lame gratuitous drag manager comments: Jim Luther
- //
- // Author: Nick Thompson, based on the original by
- // Pablo Fernicola, based on Rob Johnson's drag text sample,
- // with extensive stealing from grobbins SimpleDrag sample.
- //
- // Modification history:
- //
- // 11/26/94 nick removed dead code, tightened up the drag code, based on
- // grobbins' excellent simpledrag sample
- // 11/25/94 nick added events for dragging, this lets us do
- // source level debugging of the drag receiver, see Tumbler_aevt.
- //
- // Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved
- //
- // to do: store the document reference as a handle in the window's refcon
- //
-
-
- #define NAGELS_DEMO // pre-allocate handles
-
-
- #include <QDOffscreen.h>
- #include <Folders.h>
- #include <Drag.h>
- #include <SegLoad.h>
- #include <Types.h>
-
- #include "Tumbler_globals.h"
-
- #include "QD3D.h"
- #include "QD3DGroup.h"
- #include "QD3DStorage.h"
- #include "QD3DIO.h"
- #include "QD3DView.h"
- #include "QD3DDrawContext.h"
- #include "QD3DPick.h"
- #include "QD3DShader.h"
- #include "QD3DTransform.h"
- #include "QD3DGroup.h"
-
- #include "Tumbler_prototypes.h"
- #include "Tumbler_file.h"
- #include "Tumbler_resources.h"
- #include "Tumbler_offscreen.h"
-
-
- #include "Tumbler_AEVT.h" // grab our apleEvent handlers and data structures
- // used for debugging
- #include "Tumbler_drag.h"
-
-
-
- // Can use custom drawing procedure. Just uncomment out this line:
- // #define USE_CUSTOM_DRAWING
-
-
- // global data for my Drag Manager handlers
-
- typedef struct DragHandlerGlobals
- {
- Boolean acceptableDragFlag;
- Boolean windowIsHilightedFlag;
- } ;
-
- typedef struct DragHandlerGlobals
- DragHandlerGlobals, *DragHandlerGlobalsPtr;
-
- static DragHandlerGlobals pDragHandlerGlobals;
-
-
- //-----------------------------------------------------------------------
- // MyDrawingProc
- //
- // Simple drawing proc for dragging objects. This drawing procedure is very similar to
- // the Drag Manager's built in drawing proc, except that it uses a solid black pattern
- // to draw the region instead of using the dithered gray pattern.
- //
- // DONT USE THIS ON POWERPC as there is a quickdraw bug that leaves artifacts
- // everywhere (talk to Nitin Ganatra for the gory details).
-
-
- static
- pascal OSErr MyDrawingProc(DragRegionMessage message,
- RgnHandle showRgn, Point showOrigin,
- RgnHandle hideRgn, Point hideOrigin,
- void *dragDrawingRefCon, DragReference theDragRef)
-
- { OSErr result = paramErr;
- RgnHandle tempRgn;
-
- switch(message) {
-
- case dragRegionBegin:
-
- //
- // No initialization necessary for our drawing proc. Make sure noErr
- // is returned, otherwise the Drag Manager will revert back to it's
- // built in drawing proc.
- //
-
- result = noErr;
- break;
-
- case dragRegionDraw:
-
- //
- // Find the difference between the region needed to be shown and the
- // region needed to be hidden. Inverting the difference removes the pixels
- // that must be hidden and shows the pixels that must be shown in one step.
- //
-
- XorRgn(showRgn, hideRgn, tempRgn = NewRgn());
- InvertRgn(tempRgn);
- DisposeRgn(tempRgn);
- result = noErr;
- break;
-
- case dragRegionHide:
-
- //
- // Simply hide the region given to us by inverting it.
- //
-
- InvertRgn(hideRgn);
- result = noErr;
- break;
- }
-
- return(result);
- }
-
-
-
- //------------------------------------------------------------------------------------
- // MySendDataProc - provides data for the drag when requested.
-
- static pascal OSErr MySendDataProc(FlavorType theType, void *refCon,
- ItemReference theItem, DragReference theDrag)
-
- {
- DocumentPtr theDocument = (DocumentPtr ) refCon;
- unsigned long validSize;
-
- // so what do they want??
-
- if (theType == '3DMF') {
-
- if( theDocument->documentGroup ) {
-
- Handle theData;
- TQ3StorageObject storage;
- TQ3FileObject fd;
- TQ3TransformObject xform;
- TQ3GroupPosition position;
- Boolean didAllocate = false; // set to true if we did allocate memory
-
- if( Q3Object_IsType(theDocument->documentGroup, kQ3DisplayGroupTypeOrdered)) {
- Q3Group_GetFirstPositionOfType(theDocument->documentGroup, kQ3ShapeTypeTransform,&position);
- } else {
- Q3Group_GetFirstPosition(theDocument->documentGroup, &position);
- }
-
- xform = Q3MatrixTransform_New( &theDocument->modelRotation);
-
- position = Q3Group_AddObjectBefore(theDocument->documentGroup, position, xform);
-
- Q3Object_Dispose(xform);
-
- #ifdef NAGELS_DEMO
- // HO HO HO. Actually we *do* need a way to approximate the
- // size this handle needs to be so we can preflight
-
- if((theData = NewHandle(1024 * 1024 )) != nil) { // ask for 1M
-
- MoveHHi( theData ) ;
- HLock( theData ) ;
- didAllocate = true ;
- storage = Q3HandleStorage_New( theData, GetHandleSize( theData ) );
-
- }
- else {
-
- storage = Q3HandleStorage_New( nil, 0 );
-
- }
- #else
- storage = Q3HandleStorage_New(nil,0);
- #endif
- if (storage == nil)
- goto bail;
-
- fd = Q3File_New();
-
- if (fd == nil)
- goto bail;
-
- Q3File_SetStorage(fd, storage);
-
- Tumbler_WriteScene(fd,
- false,
- theDocument) ;
-
- Q3HandleStorage_Get(storage, &theData, &validSize);
- HLock(theData);
- SetDragItemFlavorData(theDrag, theItem, '3DMF', (Ptr) *theData,
- validSize, 0L);
- HUnlock(theData);
- Q3Object_Dispose(storage);
- Q3Object_Dispose(fd);
-
- #ifdef NAGELS_DEMO
- if( didAllocate == true ) {
- DisposeHandle(theData);
- }
- #endif
-
- }
- else {
- return(badDragFlavorErr);
- }
- }
- else {
-
- return(badDragFlavorErr);
-
- }
- return(noErr);
-
- bail:
- return(badDragFlavorErr);
- }
-
-
- //-----------------------------------------------------------------------
- // DragItemsAreAcceptable returns true if the contents (data) of
- // the drag are acceptable by a window of this application
- //
- // DragItemsAreAcceptable is called by the tracking and
- // receive handlers
- Boolean DragItemsAreAcceptable(DragReference theDrag) ;
-
- Boolean DragItemsAreAcceptable(DragReference theDrag)
- {
- OSErr retCode;
- unsigned short totalItems;
- ItemReference itemRef;
- Boolean acceptableFlag;
- HFSFlavor currHFSFlavor;
- Size flavorDataSize;
- FlavorFlags currFlavorFlags;
-
-
- acceptableFlag = false;
-
- // this app can only accept the drag of a single item
- retCode = CountDragItems(theDrag, &totalItems);
- if (retCode == noErr && totalItems == 1) {
-
- // get the reference number of the dragged item
- retCode = GetDragItemReferenceNumber(theDrag, 1, &itemRef);
- if (retCode == noErr) {
-
- // use GetFlavorFlags to check on flavor existence of PICT data
- // without forcing translation
-
- if (GetFlavorFlags (theDrag, itemRef, 'PICT', &currFlavorFlags) == noErr) {
- acceptableFlag = true;
- }
- else if (GetFlavorFlags (theDrag, itemRef, '3DMF', &currFlavorFlags) == noErr) {
- acceptableFlag = true;
- }
- else {
-
- // check if the item is a file spec for a PICT file
- flavorDataSize = sizeof(HFSFlavor);
- retCode = GetFlavorData(theDrag, itemRef, flavorTypeHFS, &currHFSFlavor,
- &flavorDataSize, 0);
-
- if (retCode == noErr && (currHFSFlavor.fileType == 'PICT'
- || currHFSFlavor.fileType == '3DMF'
- || currHFSFlavor.fileType == 'TEXT' ))
- acceptableFlag = true;
- }
- }
- }
-
- return acceptableFlag;
- }
-
-
- //-----------------------------------------------------------------------
- // DragIsNotInSourceWindow returns true if the drag in progress
- // is not in the same window it originated in
- //
- // DragIsNotInSourceWindow is called by the tracking and receive handlers
- //
- // Note that, if this application allowed items to be dragged within
- // its windows, this function would not be appropriate.
- // Instead, hilighting would probably occur in the source window
- // when the dragHasLeftSourceWindow flag is set, and the receive
- // handler wouldn't check this at all
-
- static
- Boolean DragIsNotInSourceWindow(DragReference theDrag)
- {
- DragAttributes currDragFlags;
-
- (void) GetDragAttributes(theDrag, &currDragFlags);
- return ((currDragFlags & dragInsideSenderWindow) == 0);
- }
-
-
- //-----------------------------------------------------------------------
- // MouseInContentRgn returns true if the current mouse is in the content
- // area of the window (but not necessarily in the visible rgn)
-
- static
- Boolean MouseIsInContentRgn(DragReference theDrag, WindowPtr theWindow)
- {
- Point mousePt;
-
- (void) GetDragMouse(theDrag, &mousePt, nil);
- return PtInRgn(mousePt, ((WindowPeek) theWindow)->contRgn);
- }
-
- //-----------------------------------------------------------------------
- // MyReceiveDropHandler
- //
- // Called by the Drag Manager when a drop occurs over one of the DoDragObjects document windows.
-
- pascal OSErr MyReceiveDropHandler(WindowPtr theWindow, unsigned long handlerRefCon,
- DragReference theDrag);
-
- pascal OSErr MyReceiveDropHandler(WindowPtr theWindow, unsigned long handlerRefCon,
- DragReference theDrag)
-
- {
- OSErr result;
- Rect theRect, srcRect;
- unsigned short items, index;
- ItemReference theItem;
- DragAttributes attributes;
- StScrpHandle stylHandle;
- Size dataSize, pictSize;
- short offset, selStart, selEnd, mouseDownModifiers, mouseUpModifiers, moveText;
- DocumentPtr theDocument = (DocumentPtr ) handlerRefCon;
- Point thePoint;
- TQ3Object objects = nil;
-
- Boolean dataObtainedFlag;
- OSErr retCode;
-
- OSType theDragFlavor ;
- Point mouseLoc ;
-
-
- dataObtainedFlag = false;
- if (!DragItemsAreAcceptable(theDrag) ||
- !MouseIsInContentRgn(theDrag, theWindow) ||
- !DragIsNotInSourceWindow(theDrag))
- return dragNotAcceptedErr;
-
- // We will only support one item, so get its reference number.
- result = GetDragItemReferenceNumber(theDrag, 1, &theItem);
- if (result != noErr)
- return result;
-
- GetDragAttributes(theDrag, &attributes);
- GetDragModifiers(theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers);
-
- // Loop through all of the drag items contained in this drag
-
- SetRect(&theRect, 0, 0, 0, 0);
-
- // we ensured above that we only deal with one item being dragged to us...
-
- // CountDragItems(theDrag, &items);
-
- // Get the item's reference, so we can refer to it.
- GetDragItemReferenceNumber(theDrag, 1, &theItem);
-
- // get the location the user dropped the data
- GetDragMouse(theDrag, &mouseLoc, nil ) ;
-
- // Try to get the flags for a '3DMF' flavor. If this returns noErr,
- // then we know that a '3DMF' flavor exists in the item.
-
- result = GetFlavorDataSize(theDrag, theItem, '3DMF', &dataSize);
- if (result == noErr) {
- theDragFlavor = '3DMF' ;
- }
- else if((result = GetFlavorDataSize(theDrag, theItem, 'PICT', &dataSize)) == noErr) {
- theDragFlavor = 'PICT' ;
- }
- else {
- // Couldn't get 3DMF or PICT data so try to get HFS-flavor data.
- HFSFlavor theHFSFlavor;
- dataSize = sizeof(HFSFlavor);
- result = GetFlavorData(theDrag, theItem, flavorTypeHFS,
- &theHFSFlavor, &dataSize, 0);
-
- if(theHFSFlavor.fileType != 'PICT'
- || theHFSFlavor.fileType != '3DMF'
- || theHFSFlavor.fileType != 'TEXT' ) {
- result = paramErr ;
- }
- }
-
-
- // so we either have nothing or something (in the form of 3DMF or PICT data)
- if (result == noErr) {
-
- // create a new data handle to hold the data the user just dragged in
- // this needs to be the size of the data, plus the size of the
-
- myPrivateDataHdl thePrivateData = nil ;
- long recordSize ;
-
-
- recordSize = sizeof( myPrivateDataRec ) ;
-
- // create a handle large enough for the data
- thePrivateData = (myPrivateDataHdl)NewHandle( (long)(dataSize + recordSize)) ;
-
- if( thePrivateData == nil )
- return MemError() ;
-
-
- (**thePrivateData).myTypeOfData = theDragFlavor ;
- (**thePrivateData).myDocument = theDocument ; // ideally we should store the doc in the windows refcon, this is hacky ???
- (**thePrivateData).myDataSize = dataSize ;
- (**thePrivateData).myWindow = theWindow ;
- (**thePrivateData).myLocation = mouseLoc ;
-
- // Lock and load, I dunno if GetFlavorData moves memory, I'm just assuming it may...
-
- MoveHHi( (Handle)thePrivateData ) ;
- HLock( (Handle)thePrivateData ) ;
-
- // passing (**thePrivateData) in dereferenced - ASSUMES the hnadle is locked
- GetFlavorData(theDrag, theItem, theDragFlavor, &(**thePrivateData).myData[0], &dataSize, 0L);
-
- HUnlock( (Handle)thePrivateData ) ;
-
- // package this puppy up and send it to ourselves
- SendDragRecv( thePrivateData ) ;
-
- // and dispose of the data
- DisposeHandle((Handle)thePrivateData ) ;
-
- if (attributes & dragHasLeftSenderWindow) {
- HideDragHilite(theDrag);
- }
- }
-
- return(noErr);
-
- bail:
- return(memFullErr);
- }
-
-
- //-----------------------------------------------------------------------
- // MyTrackingHandler
- //
- // This is the drag tracking handler for windows in the Dragging application.
-
- pascal OSErr MyTrackingHandler(short theMessage, WindowPtr theWindow,
- void *handlerRefCon, DragReference theDrag);
-
- pascal OSErr MyTrackingHandler(short theMessage, WindowPtr theWindow,
- void *handlerRefCon, DragReference theDrag)
-
- {
-
- RgnHandle tempRgn;
- Boolean mouseInContentFlag;
- OSErr retCode;
-
- retCode = noErr;
-
- switch (theMessage) {
-
- case dragTrackingEnterHandler:
-
- // determine if the items are acceptable and store
- // that flag in the globals, plus reset the
- // hilighted global flag
-
- pDragHandlerGlobals.acceptableDragFlag =
- DragItemsAreAcceptable(theDrag);
- pDragHandlerGlobals.windowIsHilightedFlag = false;
-
- // let the drag manager know if we can't accept this drag
- if (!pDragHandlerGlobals.acceptableDragFlag)
- retCode = dragNotAcceptedErr;
- break;
-
- case dragTrackingEnterWindow:
- case dragTrackingInWindow:
- case dragTrackingLeaveWindow:
-
- // highlighting of the window during a drag is done
- // here. Do it only if we can accept these items
- // and we're not in the source window...
-
- if (pDragHandlerGlobals.acceptableDragFlag &&
- DragIsNotInSourceWindow(theDrag)) {
-
- // unless the mouse is leaving the visible area of the
- // window, check if it's in the window's content region
-
- if (theMessage == dragTrackingLeaveWindow)
- mouseInContentFlag = false;
-
- else
- mouseInContentFlag = MouseIsInContentRgn(theDrag, theWindow);
-
- // if the mouse is in the content area and the window
- // is not yet hilighted, then do the hilighting
-
- if (mouseInContentFlag &&
- !pDragHandlerGlobals.windowIsHilightedFlag) {
-
- // set the proper clip
- ClipRect(&theWindow->portRect);
-
- // make a region bordering the window content
- tempRgn = NewRgn();
- RectRgn(tempRgn, &theWindow->portRect);
-
- // draw the hilight
- if (ShowDragHilite(theDrag, tempRgn, true) == noErr) {
- // remember that hilighting is now on
- pDragHandlerGlobals.windowIsHilightedFlag = true;
- }
-
- // free up the region
- DisposeRgn(tempRgn);
- }
-
- // else if the mouse is not in the content region
- // and the window is hilighted, erase the hilight
-
- else if (!mouseInContentFlag &&
- pDragHandlerGlobals.windowIsHilightedFlag) {
-
- // set the proper clip
- ClipRect(&theWindow->portRect);
-
- // erase the hilight and restore the port
- if (HideDragHilite(theDrag) == noErr)
-
- // remember that hilighting is now off
- pDragHandlerGlobals.windowIsHilightedFlag = false;
- }
- }
- break;
-
- // do nothing for the leaveHandler message
- case dragTrackingLeaveHandler:
- break;
-
- // let the drag manager know if we didn't recognize the message
- default:
- retCode = paramErr;
- }
-
- return retCode;
- }
-
-
- //
- // DropLocationIsFinderTrash
- //
- // Returns true if the given dropLocation AEDesc is a descriptor of the Finder's Trash.
- //
-
- static Boolean DropLocationIsFinderTrash(AEDesc *dropLocation)
-
- { OSErr result;
- AEDesc dropSpec;
- FSSpec *theSpec;
- CInfoPBRec thePB;
- short trashVRefNum;
- long trashDirID;
-
- //
- // Coerce the dropLocation descriptor to an FSSpec. If there's no dropLocation or
- // it can't be coerced into an FSSpec, then it couldn't have been the Trash.
- //
-
- if ((dropLocation->descriptorType != typeNull) &&
- (AECoerceDesc(dropLocation, typeFSS, &dropSpec) == noErr)) {
-
- HLock(dropSpec.dataHandle);
- theSpec = (FSSpec *) *dropSpec.dataHandle;
-
- //
- // Get the directory ID of the given dropLocation object.
- //
-
- thePB.dirInfo.ioCompletion = 0L;
- thePB.dirInfo.ioNamePtr = (StringPtr) &theSpec->name;
- thePB.dirInfo.ioVRefNum = theSpec->vRefNum;
- thePB.dirInfo.ioFDirIndex = 0;
- thePB.dirInfo.ioDrDirID = theSpec->parID;
-
- result = PBGetCatInfo(&thePB, false);
-
- HUnlock(dropSpec.dataHandle);
- AEDisposeDesc(&dropSpec);
-
- if (result != noErr)
- return(false);
-
- //
- // If the result is not a directory, it must not be the Trash.
- //
-
- if (!(thePB.dirInfo.ioFlAttrib & (1 << 4)))
- return(false);
-
- //
- // Get information about the Trash folder.
- //
-
- FindFolder(theSpec->vRefNum, kTrashFolderType, kCreateFolder, &trashVRefNum, &trashDirID);
-
- //
- // If the directory ID of the dropLocation object is the same as the directory ID
- // returned by FindFolder, then the drop must have occurred into the Trash.
- //
-
- if (thePB.dirInfo.ioDrDirID == trashDirID)
- return(true);
- }
-
- return(false);
- }
-
-
- //
- // DoDragObjects
- //
- // Drag the selected text in the given document.
- //
-
- short DoDragObjects(DocumentPtr theDocument, EventRecord *theEvent, RgnHandle hiliteRgn)
- {
- short result;
- RgnHandle dragRegion, tempRgn;
- Point theLoc;
- DragReference theDrag;
- StScrpHandle theStyl;
- AEDesc dropLocation;
- DragAttributes attributes;
- short mouseDownModifiers, mouseUpModifiers, copyText;
- unsigned long validSize;
-
- if( theDocument->documentGroup ) {
-
- Handle theData;
- TQ3StorageObject storage;
- TQ3FileObject fd;
- TQ3GroupPosition position;
- TQ3TransformObject xform;
-
- DragSendDataUPP mySendDataProcUPP ;
-
- //Q3Object_Dispose(pickObject);
-
- CopyRgn(hiliteRgn, dragRegion = NewRgn());
- SetPt(&theLoc, 0, 0);
- LocalToGlobal(&theLoc);
- OffsetRgn(dragRegion, theLoc.h, theLoc.v);
-
- //
- // Wait for the mouse to move to the mouse button to be released. If the mouse button was
- // released before the mouse moves, return false. Returing false from DoDragObjects means that
- // a drag operation did not occur.
- //
-
- if (! WaitMouseMoved(theEvent->where)) {
- return(false);
- }
-
- // create a new reference for a track to pass to track drag
- NewDrag(&theDrag);
-
- // We promise '3DMF' and 'PICT'. If a receiver requests either, the Drag Manager
- // will call our MySendDataProc to provide the data at drop time. The MySendDataProc
- // is specified by calling SetDragSendProc.
- AddDragItemFlavor(theDrag, 1, '3DMF', nil, 0L, 0L);
- // AddDragItemFlavor(theDrag, 1, 'PICT', nil, 0L, 0L);
-
- mySendDataProcUPP = NewDragSendDataProc(MySendDataProc) ;
- SetDragSendProc(theDrag, mySendDataProcUPP, (void *) theDocument);
-
- // Set the item's bounding rectangle in global coordinates.
- SetDragItemBounds(theDrag, 1, &(**dragRegion).rgnBBox);
-
- // Prepare the drag region.
- tempRgn = NewRgn();
- CopyRgn(dragRegion, tempRgn);
- InsetRgn(tempRgn, 1, 1);
- DiffRgn(dragRegion, tempRgn, dragRegion);
- DisposeRgn(tempRgn);
-
- // on PPC the drawing proc leaves artifacts on the display when
- // highlighting and upon removal of highlighting for a window, so
- // although I may prefer the drawing that my custom proc does, I
- // just use the default. This may be a bug in the drag manager
- // or it may be us, but right now we'll just a void doing this and fix later
- // SetDragDrawingProc(theDrag,NewDragDrawingProc(MyDrawingProc), 0L);
-
- // Drag the stuff. TrackDrag will return userCanceledErr if the drop zoomed-back
- // for any reason.
- result = TrackDrag(theDrag, theEvent, dragRegion);
-
- // get rid of the UPP
- DisposeRoutineDescriptor( mySendDataProcUPP ) ;
-
- if (result != noErr && result != userCanceledErr) {
- return(true);
- }
-
- // Check to see if the drop occurred in the Finder's Trash. If the drop occurred
- // in the Finder's Trash and a copy operation wasn't specified, delete the
- // source selection. Note that we can continute to get the attributes, drop location
- // modifiers, etc. of the drag until we dispose of it using DisposeDrag.
- GetDragAttributes(theDrag, &attributes);
- if (!(attributes & dragInsideSenderApplication)) {
-
- GetDropLocation(theDrag, &dropLocation);
-
- GetDragModifiers(theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers);
- copyText = (mouseDownModifiers | mouseUpModifiers) & optionKey;
-
- if ((!copyText) && (DropLocationIsFinderTrash(&dropLocation))) {
- theDocument->dirty = true;
- Q3Object_Dispose(theDocument->documentGroup);
- theDocument->documentGroup = nil;
- }
-
- AEDisposeDesc(&dropLocation);
- }
-
- // Dispose of the drag.
- DisposeDrag(theDrag);
- DisposeRgn(dragRegion);
- return(true);
- }
- bail:
- return(false);
- }
-
-
-
-
-